/*  File Name	: ChatService.cpp
 *  Author		: Javie Pong
 *	 E-mail		: 823960168@qq.com
 *  Created on	: 2012-10-4
 *  Description:
 */

#include "ChatService.h"
#include "ChatMonitor.h"

#define MAX_CHAT_CONTENT_LEN 70
#define CHAT_INTERVAL 2

ChatService::ChatService(int p)
{
	this->reset();
}

ChatService::~ChatService()
{

}

int ChatService::open(void *p)
{
	if(this->monitor()->bind_service(this)<0)
	{
		return -1;
	}
	if(super::open(this->reactor())<0)
	{
		return -1;
	}
	return 0;
}

int ChatService::handle_input(int fd)
{
	this->last_recv_msg_ =  TimeValue::now_time_in_sec();
	return this->recv_msg();
}

int ChatService::handle_output(int fd)
{
	return 0;
}

int ChatService::handle_timeout(void)
{
	return 0;
}

int ChatService::handle_close(int handle,ReactorMask mask)
{
	super::handle_close(handle,mask);
	return this->monitor()->handle_close(this);
}

int ChatService::is_flash_sanbox(MessageBlock *mb)
{
	//flash sandbox
	static const char szFlashSocketVerify[] = "<policy-file-request/>";
	static const char szFlashSocketVerifyReply[] =
			"<?xml version=\"1.0\"?><cross-domain-policy><allow-access-from domain=\"*\" to-ports=\"*\"/></cross-domain-policy>\0";

	if (mb->data_len()== sizeof(szFlashSocketVerify)
			&& 0== strncmp(szFlashSocketVerify,mb->rd_ptr(),
							sizeof(szFlashSocketVerify)))
	{
		mb->reset();
		mb->write(szFlashSocketVerifyReply,sizeof(szFlashSocketVerifyReply));
		this->send_msg(mb, mb->data_len());
		this->monitor()->msg_pool()->pop(mb);
		return 0;
	}
	return -1;
}

int ChatService::recv_msg(const int limit_size)
{
	MessageBlock *mb = NULL;
	if(this->monitor()->msg_pool()->pop(mb)!=0)
	{
		LOG((ERROR_LOG,"ChatService::recv_msg-1->pop error"));
		return -1;
	}

	int len =0;
	bool has_data = false;
	do
	{
		mb->reset();
		len = super::recv_msg(mb, mb->size());
		if (len == -1 && (errno == EWOULDBLOCK || errno==EINTR))
		{
			this->monitor()->msg_pool()->push(mb);
			break;
		}
		else if (len <= 0)
		{
			LOG((DEBUG_LOG,"ChatService::recv_msg-->recv:[%d],error:[%d:%s]",
					len,errno,strerror(errno)));
			this->monitor()->msg_pool()->push(mb);
			return -1;
		}
		if (is_flash_sanbox(mb)==0)
		{
			continue;
		}
		has_data = true;
		if (this->make_block(mb, len) == -1)
		{
			LOG((ERROR_LOG,"ChatService::recv_msg-->make_block error"));
			return -1;
		}
	}while (len > 0);

	if(TimeValue::now_time_in_sec()-this->last_recv_msg_<CHAT_INTERVAL)
	{
		this->monitor()->msg_pool()->push(mb);
		MessageBlock mb_send(sizeof(int)*10);
		mb_send << (int)sizeof(int)*3
				<< STC_CHATER_CONTENT_ERROR << ERROR_CHAT_TOO_FAST;
		this->send_msg(&mb_send,mb_send.data_len());
		return 0;
	}

	if(!has_data)
	{
		return 0;
	}

	int result = 0;
	do
	{
		MessageBlock *mb = NULL;
		if(this->monitor()->msg_pool()->pop(mb)!=0)
		{
			LOG((ERROR_LOG,"ChatService::recv_msg-2->pop error"));
			return -1;
		}

		*mb	<<this->unique_id() << this->role_id();
		result = this->get_block(mb);
		if(result<0)
		{
			LOG((ERROR_LOG,"ChatService::recv_msg-->get_block error[%d]",result));
			this->monitor()->msg_pool()->push(mb);
			return -1;
		}
		else if(mb->data_len()>MAX_CHAT_CONTENT_LEN)
		{
			this->monitor()->msg_pool()->push(mb);

			MessageBlock mb_send(sizeof(int)*10);
			mb_send << (int)sizeof(int)*3
					<< STC_CHATER_CONTENT_ERROR << ERROR_CHAT_CONTENT_LEN;
			this->send_msg(&mb_send,mb_send.data_len());
			return 0;
		}
		else if(result==0)
		{
			this->monitor()->msg_pool()->push(mb);
			return 0;
		}
		//if (is_flash_sanbox(mb)<0)
		{
			this->monitor()->request_mb_push(mb);
		}
	}
	while(result==2);
	return 0;
}

void ChatService::reset(void)
{
	this->role_id_ = 0;
}

std::string ChatService::name(void)
{
	return "ChatService";
}

const int ChatService::role_id(void)
{
	return this->role_id_;
}

void ChatService::role_id(int role_id)
{
	this->role_id_ = role_id;
}
